/***************************************************
 ** @Desc : This file for 扫码支付
 ** @Time : 2018.09.21 9:28 
 ** @Author : Joker
 ** @File : scan_pay
 ** @Last Modified by : Joker
 ** @Last Modified time: 2018.09.21 9:28
 ** @Software: GoLand
****************************************************/
package controllers

import (
	"github.com/astaxie/beego"
	"TheKingOfHearts/utils"
	"encoding/json"
	"net/http"
	"net/url"
	"io/ioutil"
	"TheKingOfHearts/models"
	"fmt"
)

type ScanPay struct {
	beego.Controller
}

/* *
 * @Author: Joker
 * @Description: 预下单接口
 * @Date: 2018.09.22 10:33
 * @Param:
 * @return: out_trade_no: 订单号
 * @return: qr_code: 扫码地址
 **/
// @router /scanpay/pre_order.py/?:params
func (this *ScanPay) TradePrecrede() {
	//构造请求参数
	out_trade_no := utils.GenerateUUID()    //商户订单号 (利用缓存生成,确保唯一)
	total_amount := "0.01"                  //订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
	subject := "Joker are testing product!" //订单标题
	store_id := "Test_000001"               //商户门店编号
	timeout_express := "90m"                //该笔订单允许的最晚付款时间,逾期将关闭交易,90分钟
	seller_id := utils.SELLER_ID            //默认为卖家支付宝用户ID (多账号收款情况下,任选其一)
	req_params := map[string]string{
		"out_trade_no":            out_trade_no,
		"seller_id":               seller_id,
		"total_amount":            total_amount,
		"subject":                 subject,
		"store_id":                store_id,
		"timeout_express":         timeout_express,
		"sys_service_provider_id": utils.SELLER_ID,
	}

	//生成请求内容
	//请求内容(由请求参数拼接成的JSON串)
	content, e := json.Marshal(req_params)
	if e != nil {
		utils.LogError("Failed to generate request context for: ", e)
	}
	bizContent := string(content)

	//构造请求头(固定值)
	timestamp := utils.GetNowTime() //请求时间,格式; 2018-09-21 10:53:34
	method := utils.PRECREATE       //请求API
	appId := utils.APPID            //应用号
	signType := utils.SECID         //加密算法
	version := utils.VERSIONS       //接口版本
	format := utils.FORMAT          //交互数据格式:JSON
	charset := utils.CHARSET        //请求使用的编码格式
	notify_url := ""                //回调地址

	//构造参与签名的map
	sign_map := map[string]string{
		"timestamp":   timestamp,
		"method":      method,
		"app_id":      appId,
		"sign_type":   signType,
		"version":     version,
		"biz_content": bizContent,
		"format":      format,
		"charset":     charset,
		"notify_url":  notify_url,
	}

	//生成签名
	sign_string := utils.ToStringByMapRemoveSign(sign_map)
	sign_RSA, err0 := utils.SHA256WithRSAToSign([]byte(sign_string), []byte(utils.PRIVATE_KEY))
	if err0 != nil {
		utils.LogError("Failed to generate sign_RSA for: ", err0)
	}
	sign := utils.Base64Encode(sign_RSA) //签名

	//发送请求
	resp, err1 := http.PostForm(utils.REQ_URL, url.Values{
		"timestamp":   {timestamp},
		"method":      {method},
		"app_id":      {appId},
		"sign_type":   {signType},
		"version":     {version},
		"biz_content": {bizContent},
		"format":      {format},
		"charset":     {charset},
		"notify_url":  {notify_url},
		"sign":        {sign},
	})

	//请求出错
	if err1 != nil {
		utils.LogError("TradePrecrede failed to submit form: ", err1)
	}
	defer resp.Body.Close()

	//接收返回值
	html, err2 := ioutil.ReadAll(resp.Body)
	if err2 != nil {
		utils.LogError("TradePrecrede failed to receive data: ", err2)
		utils.LogError(err2)
	}
	//编码格式转为UTF-8
	body, err3 := utils.GbkToUtf8(html)
	if err3 != nil {
		utils.LogNotice("GBK failed to transfer utf-8 for: ", err3)
	}

	//do something,handle receive data
	publicParams := models.ResponsePublicParams{}
	json.Unmarshal([]byte(string(body)), &publicParams) //string to json

	verify_string := publicParams.AlipayTradePrecreateResponse //待签名的串
	sign_json, _ := json.Marshal(verify_string)
	fmt.Println("====================== show sign_json =======================")
	fmt.Println(string(sign_json))
	return_sign := publicParams.Sign //返回的签名

	verifySign := utils.SHA256WithRSAVerifySign(string(sign_json), return_sign)
	if verifySign == nil {
		fmt.Println("success")
	} else {
		fmt.Println("failed  ========  ", verifySign)
	}
}

/* *
 * @Author: Joker
 * @Description: 交易查询接口
 * @Date: 2018.09.25 10:41
 * @Param: 
 * @return: INPROCESS
 **/
// @router /scanpay/query_order.py/?:params
func (this *ScanPay) TradeQuery() {
	//构造请求参数
	out_trade_no := "261683767410689" //需要查询的商户订单号
	trade_no := ""     //支付宝交易号,和商户订单号不能同时为空
	req_params := map[string]string{
		"out_trade_no": out_trade_no,
		"trade_no":     trade_no,
	}

	//生成请求内容
	//请求内容(由请求参数拼接成的JSON串)
	content, e := json.Marshal(req_params)
	if e != nil {
		utils.LogError("Failed to generate request context for: ", e)
	}
	bizContent := string(content)

	//构造请求头(固定值)
	timestamp := utils.GetNowTime() //请求时间,格式; 2018-09-21 10:53:34
	method := utils.QUERY           //请求API
	appId := utils.APPID            //应用号
	signType := utils.SECID         //加密算法
	version := utils.VERSIONS       //接口版本
	format := utils.FORMAT          //交互数据格式:JSON
	charset := utils.CHARSET        //请求使用的编码格式
	notify_url := ""                //回调地址
	app_auth_token := ""            //若需要代替商户发起当面付的收单请求,则此参数必填

	//构造参与签名的map
	sign_map := map[string]string{
		"timestamp":      timestamp,
		"method":         method,
		"app_id":         appId,
		"sign_type":      signType,
		"version":        version,
		"biz_content":    bizContent,
		"format":         format,
		"charset":        charset,
		"notify_url":     notify_url,
		"app_auth_token": app_auth_token,
	}

	//生成签名
	sign_string := utils.ToStringByMapRemoveSign(sign_map)
	sign_RSA, err0 := utils.SHA256WithRSAToSign([]byte(sign_string), []byte(utils.PRIVATE_KEY))
	if err0 != nil {
		utils.LogError("Failed to generate sign_RSA for: ", err0)
	}
	sign := utils.Base64Encode(sign_RSA) //签名

	//发送请求
	resp, err1 := http.PostForm(utils.REQ_URL, url.Values{
		"timestamp":      {timestamp},
		"method":         {method},
		"app_id":         {appId},
		"sign_type":      {signType},
		"version":        {version},
		"biz_content":    {bizContent},
		"format":         {format},
		"charset":        {charset},
		"notify_url":     {notify_url},
		"app_auth_token": {app_auth_token},
		"sign":           {sign},
	})

	//请求出错
	if err1 != nil {
		utils.LogError("TradePrecrede failed to submit form: ", err1)
	}
	defer resp.Body.Close()

	//接收返回值
	html, err2 := ioutil.ReadAll(resp.Body)
	if err2 != nil {
		utils.LogError("TradePrecrede failed to receive data: ", err2)
		utils.LogError(err2)
	}
	//编码格式转为UTF-8
	body, err3 := utils.GbkToUtf8(html)
	if err3 != nil {
		utils.LogNotice("GBK failed to transfer utf-8 for: ", err3)
	}

	//do something,handle receive data
	fmt.Println("====================== show response =======================")
	fmt.Println(string(body))
}